import sys
import os
import subprocess
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton, QFileDialog, QTextEdit, QLabel, QTabWidget, QCheckBox, QMessageBox, QHBoxLayout
from PySide6.QtCore import QThread, Signal

def get_python_executable():
    """获取 Python 可执行文件路径"""
    if getattr(sys, 'frozen', False):
        # 如果是打包后的可执行文件
        return os.path.join(sys._MEIPASS, 'python311.dll')  # Windows
    else:
        # 正常开发环境
        return sys.executable

class Worker(QThread):
    output_signal = Signal(str)

    def __init__(self, folder_path, scripts):
        super().__init__()
        self.folder_path = folder_path
        self.scripts = scripts


    def run(self):
        try:
            if hasattr(sys, '_MEIPASS'):
                script_dir = sys._MEIPASS  # 在打包后的环境中
            else:
                script_dir = os.path.dirname(os.path.abspath(__file__))  # 在开发环境中
            os.chdir(script_dir)  # 设置工作目录

            for script in self.scripts:
                self.output_signal.emit(f"正在执行 {script}...\n")
                process = subprocess.Popen(
                    [get_python_executable(), os.path.join(script_dir, script), self.folder_path],
                    stdout=subprocess.PIPE,
                    stderr=subprocess.PIPE,
                    text=True,
                    encoding='utf-8',
                    errors='replace'
                )
                for line in iter(process.stdout.readline, ''):
                    self.output_signal.emit(line)
            
                process.stdout.close()
                process.wait()
                if process.returncode != 0:
                    error_output = process.stderr.read()
                    self.output_signal.emit(f"执行 {script} 失败:\n{error_output}\n")
                else:
                    self.output_signal.emit(f"执行 {script} 成功\n")
            self.output_signal.emit(f"勾选的脚本文件已经全部执行。\n")    
        except Exception as e:
            self.output_signal.emit(f"发生错误: {str(e)}\n")
class App(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("python文件重复度检测工具 Author:luwei")
        self.setGeometry(100, 100, 600, 400)

        layout = QVBoxLayout()

        self.label = QLabel("请选择测试数据集的文件夹路径")
        layout.addWidget(self.label)

        # 调整文件夹路径文本框的高度
        self.folder_path_edit = QTextEdit()
        self.folder_path_edit.setReadOnly(True)
        self.folder_path_edit.setFixedHeight(30)  # 设置固定高度
        layout.addWidget(self.folder_path_edit)

        # 创建一个水平布局用于放置按钮
        button_layout = QHBoxLayout()
        
        self.btn_browse = QPushButton("选择文件夹")
        self.btn_browse.clicked.connect(self.browse_folder)
        button_layout.addWidget(self.btn_browse)

        self.btn_open_output_folder = QPushButton("打开输出文件夹")
        self.btn_open_output_folder.clicked.connect(self.open_output_folder)
        button_layout.addWidget(self.btn_open_output_folder)

        self.btn_run = QPushButton("确认并执行")
        self.btn_run.clicked.connect(self.run_scripts)
        button_layout.addWidget(self.btn_run)

        layout.addLayout(button_layout)

        # 创建选项卡
        self.tab_widget = QTabWidget()
        self.tab_widget.addTab(self.create_script_tab("sim-segment.py", "通过有条件筛选的字符段匹配,输出文件重复关系check_files.txt"), "Sim Segment")
        self.tab_widget.addTab(self.create_script_tab("ast-check.py", "通过过滤位置信息的py文件语义树,输出重复项结果、相似度结果、相似度热图"), "AST Check")
        self.tab_widget.addTab(self.create_script_tab("code-token.py", "格式化文件，去除空行后统计完全相同的行信息，输出代码重复率、重复代码片段"), "Code Token")
        layout.addWidget(self.tab_widget)

        # 添加输出信息文本框标签
        self.output_label = QLabel("程序运行进程提示:")
        layout.addWidget(self.output_label)

        # 输出信息文本框
        self.output_edit = QTextEdit()
        self.output_edit.setReadOnly(True)
        layout.addWidget(self.output_edit)

        self.setLayout(layout)

    def browse_folder(self):
        folder_path = QFileDialog.getExistingDirectory(self, "选择文件夹")
        if folder_path:
            self.folder_path_edit.setPlainText(folder_path)

    def create_script_tab(self, script_name, script_description):
        tab_widget = QWidget()
        tab_layout = QVBoxLayout()
        
        checkbox = QCheckBox(f"执行 {script_name}")
        checkbox.setChecked(True)
        tab_layout.addWidget(checkbox)

        # 添加脚本描述标签
        description_label = QLabel(script_description)
        tab_layout.addWidget(description_label)

        tab_widget.setLayout(tab_layout)
        return tab_widget

    def run_scripts(self):
        folder_path = self.folder_path_edit.toPlainText()
        if not folder_path:
            self.output_edit.setPlainText("请先选择文件夹路径。")
            return
    
        current_directory = os.path.dirname(os.path.abspath(__file__))
        if hasattr(sys, '_MEIPASS'):
            current_directory = sys._MEIPASS  # 如果是在打包后的环境中运行
        
        scripts = []
        script_map = {
            "Sim Segment": "sim-segment.py",
            "AST Check": "ast-check.py",
            "Code Token": "code-token.py"
        }

        for index in range(self.tab_widget.count()):
            tab_widget = self.tab_widget.widget(index)
            checkbox = tab_widget.layout().itemAt(0).widget()
            if checkbox.isChecked():
                script_name = script_map[self.tab_widget.tabText(index)]
                script_path = os.path.join(current_directory, script_name)
                scripts.append(script_path)

        if not scripts:
            self.output_edit.setPlainText("请至少选择一个脚本。")
            return

        self.worker = Worker(folder_path, scripts)
        self.worker.output_signal.connect(self.update_output)
        self.worker.start()

    def update_output(self, message):
        self.output_edit.append(message)

    def open_output_folder(self):
        folder_path = self.folder_path_edit.toPlainText()
        output_folder = os.path.join(folder_path, "输出结果")

        if os.path.exists(output_folder):
            os.startfile(output_folder)
        else:
            QMessageBox.warning(self, "警告", "请先执行查重程序。")

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = App()
    window.show()
    sys.exit(app.exec())
